<template>
    <view class="rx-select-disabled" v-if="readOnly">
        {{disabledLabel}}
    </view>
    <view v-else class="rx-select-box">
        <view class="rx-select-multiple" @click.stop="selectTree">
                <div class="rx-select-tag" v-for="item of curLabel">
                    <span>{{item.label}}</span>
                    <span class="rx-select-close" v-if="!readOnly" @click.stop="deleteClose(item)">
                    <my-icon type="icon-close"/>
                </span>
                </div>
            <span class="rx-select-fold-icon" v-if="curValue.length === 0">
                <my-icon type="icon-icon-test40"/>
            </span>
            <span class="rx-select-fold-icon" v-else @click.stop="empty" >
                <my-icon type="icon-icon-test26"/>
             </span>
        </view>
    </view>
    <next-tree
        ref="nextTree"
        :selectParent="true"
        :checkStrictly="false"
        :funcMode="isMultiple"
        :treeData="options"
        :ifSearch="ifSearch"
        valueKey="value"
        themeColor="#4285f2"
        @confirm="setValue"
        :loadData="metadata.options.async?loadData:''"
    />
</template>

<script>
/**
 * 树选择
 * https://ext.dcloud.net.cn/plugin?id=12265
 */
import MForm from "../js/MForm";
import {FormApi} from "@/api/FormApi.js";
import Util from "@/js/Util.js";
import BaseComplex from "../js/BaseComplex";
export default {
    name: "MTreeSelect",
    mixins:[MForm,BaseComplex],
    inject:{
        formVm:{
            default:()=>{return{}}
        }
    },
    data() {
        return {
            //当前选中的值
            curValue: [],
            //当前选中的文本
            curLabel: [],
            options: [],
            flag:false,
        }
    },
    computed:{
        valMode(){
            return  this.metadata.options.valMode ;
        },
        isMultiple(){
            return this.metadata.options.mode == 'multiple'? "checkbox" : "radio" ;
        },
        ifSearch(){
            return this.metadata.options.showSearch && !this.metadata.options.async ;
        },
        disabledLabel(){
            let lable = []
            this.curLabel.forEach(res=>{
                lable.push(res.label)
            })
            return lable.join(',')
        }
    },
    created() {
        this.initTreeDataSource();
        this.setCurValue(this.value,false);
    },
    methods: {
        deleteClose(item) {
            //多值
            if (this.valMode == 'double') {
                //多选
                let list =JSON.parse(this.value);
                if(list.value){
                    let value = list.value.split(",");
                    let label = list.label.split(",");
                    value.filter((res,index)=>{
                        if(item.value ==res){
                            value.splice(index,1)
                        }
                    })
                    if(!value || value.length==0){
                        this.setData("");
                        return;
                    }
                    label.filter((res,index)=>{
                        if(item.label ==res){
                            label.splice(index,1)
                        }
                    })
                    let json = {
                        label:label.join(','),
                        value:value.join(',')
                    }
                    this.setData(JSON.stringify(json));
                }
            } else {
                //多选
                this.curValue.filter((res,index)=>{
                    if(item.value ==res){
                        this.curValue.splice(index,1)
                    }
                })
                this.setData(this.curValue.join(','));
            }
        },
        selectTree(){
            this.$refs.nextTree.showTree=true;
        },
        /**
         * 初始化数据来源
         * @returns {Promise<void>}
         */
        async initTreeDataSource(){
            if(this.flag){
                return;
            }
            let self=this;
            let json=this.metadata.options.sourceConfig;
            let valueSource=this.metadata.options.valueSource;
            let _async = this.metadata.options.async ;
            //处理外部传如的自定义方式，表单无此配置
            if(valueSource=='custom'){
                this.options=json.options;
                this.flag = true;
            }else if(valueSource=='dic'){
                if (_async) {
                    this.getDataByDic(json, "0");
                } else {
                    this.getDataByDic(json, "");
                }
            }else if(valueSource=='sql'){
                let  _sqlKey = json.sqlKey ;
                let params = {};
                if (valueSource == "sql" && _sqlKey != "") {
                    if (_async) {
                        let fatherNode = json.fatherNode;
                        let obj = {};
                        obj[fatherNode] = json.firstParentNode || "0";
                        params["params"] = JSON.stringify(obj);
                    }
                    this.getDataBySql(json, params);
                }
            }
            else if(valueSource=='interface'){
                await this.loadByInterface(json,function (data){
                    self.options=data;
                });
            }else if(valueSource=='grant'){
                await this.loadByGrant(json,function (data){
                    self.options=data;
                });
            }
            else if(valueSource=='script'){
                await this.getScriptData(json,function (data){
                    self.options=data;
                });
            }
        },
        getDataByDic(config, parentId ,callback) {
            let  dickey = config.dicKey;
            let _async = this.metadata.options.async ;
            let cacheKey = `${dickey}_${parentId}`;
            if(this.formVm.fieldSourceCache[cacheKey]){
                this.options = this.formVm.fieldSourceCache[cacheKey];
                return ;
            }
            if (dickey) {
                let self = this ;
                FormApi.loadDicByPidAndDicId(dickey, parentId).then(res => {
                    let  arr = [];
                    if (res.length > 0) {
                        for (let  i = 0; i < res.length; i++) {
                            let  obj = {
                                id: res[i].pkId,
                                pId: res[i].parentId,
                                label: res[i].name,
                                value: res[i].value,
                                isLeaf: res[i].childAmount > 0 ? false : true
                            };
                            arr.push(obj);
                        }
                        //是否异步
                        if (_async) {
                            arr = Util.listToTree(arr, "id", "pId");
                            self.genTreeData(arr, config,cacheKey);
                            if(callback){
                                callback(arr);
                            }
                        } else {
                            let op = Util.listToTree(arr, "id", "pId");
                            self.options = op ;
                            if(cacheKey){
                                self.formVm.fieldSourceCache[cacheKey] = op;
                            }
                            Util.genTreeData(this.options, "label", "value", "value");
                        }
                    }
                })
            }
        },
        //自定义sql
        getDataBySql(config, params ,callback) {
            let key = config.sqlKey;
            let textField = config.textField;
            let valueField = config.valueField;
            let fatherNode = config.fatherNode;
            let _async = this.metadata.options.async ;
            let deploy = {
                textfield: textField,
                valuefield: valueField,
                fatherNode: fatherNode
            };
            let _self = this ;
            params["deploy"] = JSON.stringify(deploy);
            if(config.params && config.params.length>0){
                if(!params["params"]){
                    params["params"]='{}';
                }
                let paramsInput = this.getParamsInput(config.params);
                if(paramsInput){
                    params["params"]=JSON.stringify(Object.assign(JSON.parse(params["params"]),paramsInput));
                }
            }
            FormApi.queryForJson(key, params).then(res => {
                let data = res.data;
                let arr = [];
                if(!data){ return }
                for (let i = 0; i < data.length; i++) {
                    let obj = {
                        id: data[i][valueField],
                        pId: data[i][fatherNode],
                        label: data[i][textField],
                        value: data[i][valueField],
                        isLeaf: data[i].CHILDS > 0 ? false : true,
                        ...data[i]
                    };
                    arr.push(obj);
                }
                //是否异步
                if (_async) {
                    arr =Util.listToTree(arr, "id", "pId");
                    _self.genTreeData(arr, config);
                    if(callback){
                        callback(arr);
                    }
                } else {
                    _self.options = Util.listToTree(arr, "id", "pId");
                    Util.genTreeData(_self.options, "label", "value", "value");
                }
            });
        },
        setCurValue(value,isInit){
            //选择的数据
            let selectValue=[];
            if(value){
                //多值
                if(this.valMode=='double'){
                    let obj = JSON.parse(value);
                    if(obj.value){
                        //多选
                        if(this.isMultiple=='checkbox'){
                            selectValue=obj.value.split(",");
                        }else {
                            selectValue=[obj.value];
                        }
                    }
                }else {
                    //多选
                    if(this.isMultiple=='checkbox'){
                        selectValue=value.split(",");
                    }else {
                        selectValue=[value];
                    }
                }
            }
            this.curLabel=[];
            this.curValue=selectValue;
            this.checkedTreeData(this.options, selectValue);
            //双值 且在树中未找到选项时 直接取数据中的label
            if(value && this.valMode=='double' && this.curLabel.length==0){
                let obj = JSON.parse(value);
                let values=obj.value.split(",");
                let labels=obj.label.split(",");
                for (let i = 0; i < values.length; i++) {
                    this.curLabel.push({
                        label:labels[i],
                        value:values[i],
                    });
                }
            }
            //初始化时不需要处理关联字段
            if(!isInit) return;
            //处理自定义查询关联字段
            let _value="";
            if(this.curValue){
                if(this.valMode == "double"){
                    if(this.isMultiple){
                        _value=[];
                        this.curValue.forEach(item=>{_value.push(item.value);})
                    }else {
                        _value=this.curValue.value;
                    }
                }else {
                    _value=this.curValue;
                }
            }
            this.handFieldMapping(_value);
        },
        getNodePath (obj,field, value){
            let getParent = (list,field, value) => {
                for (let i in list) {
                    if ( list[i][field] === value) {
                        return [list[i]]
                    }
                    if (list[i].children) {
                        let node = getParent(list[i].children,field,value);
                        if (node !== undefined) {
                            return node.concat(list[i])
                        }
                    }
                }
            }
            return getParent(obj,field, value)
        },
        buildPath(value){
            let arr = this.getNodePath(this.options,"value",value);
            let path="";
            if (arr && arr.length>0){
                path = this.getPathName(arr);
            }
            return path
        },
        getPathName(arr){
            //获取链式路径
            let str = '';
            let level = arr.length - 1 ;
            for(let i = level ;i>=0;i--){
                str += `${arr[i].label}`+ (i === 0?"":'/')
            }
            return str ;
        },
        checkedTreeData(treeData, selectValue) {
            (treeData || []).map(item => {
                if (selectValue.indexOf(item.value) !== -1) {
                    let label = item.label
                    if (this.metadata.options.showFullPath){
                        label = this.buildPath(item.key)
                    }
                    this.curLabel.push({
                        label:label,
                        value:item.key,
                    });
                    item.checked = true
                } else {
                    item.checked = false
                }
                if (item.children && item.children.length) {
                    this.checkedTreeData(item.children, selectValue)
                }
            })
        },
        setValue(data){
            let val="";
            if(data){
                let values=[];
                let labels=[];
                for (let i = 0; i < data.length; i++) {
                  let label = data[i].label
                  if (this.metadata.options.showFullPath){
                    label = this.buildPath(data[i].key)
                  }
                    values.push(data[i].value);
                    labels.push(label);
                }
                //多值
                if(this.valMode=='double'){
                    let obj={
                        label:labels.join(","),
                        value:values.join(",")
                    }
                    val=!obj.value ? '':JSON.stringify(obj);
                }else {
                    val=values.join(",");
                }
            }
            this.setData(val);
        },
        genTreeData(ary, config,cacheKey) {
            if(!ary || ary.length==0){
                return;
            }
            ary.forEach((item) => {
                if(!item["isLeaf"]){
                    item.children=[];
                }
            });
            let firstParentNode = config.firstParentNode || "0";
            if(ary[0].pId != firstParentNode){
                this.setChildren(this.options,ary,ary[0].pId)
            }else {
                this.options = ary;
            }
            this.formVm.fieldSourceCache[cacheKey] = this.options ;
        },
        setChildren(options,ary,pId){
            options.forEach((item) => {
                if(item.id == pId){
                    item.children =ary;
                }else if(item.children) {
                    this.setChildren(item.children,ary,pId);
                }
            });
        },
        async loadData(treeNode) {
            let config=this.metadata.options.sourceConfig;
            let _async = this.metadata.options.async ;
            let valueSource=this.metadata.options.valueSource;
            if (_async && treeNode.source.children.length==0) {
                return new Promise(resolve => {
                    const { id } = treeNode.source;
                    let  params = {};
                    if (valueSource == "sql") {
                        let  fatherNode = config.fatherNode;
                        let  obj = {};
                        obj[fatherNode] = id;
                        params["params"] = JSON.stringify(obj);
                    }
                    if (valueSource == "dic") {
                        this.getDataByDic(config, id,function (ary){
                            resolve(ary);
                        });
                    }
                    else if (valueSource == "sql") {
                        this.getDataBySql(config, params,function (ary) {
                            resolve(ary);
                        });
                    }
                });
            }
            return [];
        },
        getLabel(){
            return this.curLabel?this.curLabel.join():"";
        },
        empty(){
            this.setData('');
        }
    },
    watch: {
        "value":{
            handler:function (val){
                this.setCurValue(val,true);
            },
            deep: true
        },
        options: {
            handler(val) {
                if(!val || val.length==0){
                    this.setValue("");
                }else {
                    this.setCurValue(this.value,false);
                }
            },
            deep: true
        },
        /**
         * 控件单独使用时传递下拉树选项
         * valueSource="custom"
         * sourceConfig.options=[]
         */
        "metadata.options.sourceConfig.options":{
            handler:function (val,oldVal){
                this.initTreeDataSource();
            },
            deep:true
        },
    },
}
</script>

<style scoped>
.rx-select-box{
    border: 1px solid #e5e5e5;
    box-sizing: border-box;
    border-radius: 4px;
    padding-left: 0.625rem;
    position: relative;
    -webkit-user-select: none;
    -moz-user-select: none;
    user-select: none;
    width: 100%;
    min-height: 2rem;
    margin-top: 0.5rem;
}
.rx-select-multiple{
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    min-height: 2rem;
    padding-right: 2.25rem;
    position: relative;
}
.rx-select-close{
    margin: 0.1rem 0rem 0rem 0.2rem;
}
.rx-select-close > i{
    font-size: 0.7rem;
    color: rgba(34, 34, 34, 1);
}
.rx-select-tag{
    display: flex;
    align-items: center;
    margin-right: 0.5rem;
    font-size: 0.9rem;
}


.rx-select-fold-icon i{
    font-size: 1rem;
    color:rgba(204, 204, 204, 1);
}
.rx-select-fold-icon{
    position: absolute;
    right:0rem;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    width: 2.25rem;
    height: 100%;
    align-items: center;
    justify-content: center;
}
.rx-select-disabled{
    background: rgba(245, 246, 249, 1);
    display: flex;
    align-items: center;
    padding: 0.5rem;
    border-radius: 4px;
    border: none;
    margin-top: 0.5rem;
    min-height: 1rem;
}
</style>
